热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Linux|041_Shell编程(3)Bash变量

shel

全文6985字,阅读需18分钟。


目录

四、Bash 变量

    4.1 变量的定义

    4.2 变量的分类

    4.3 用户自定义变量

        4.3.1 变量定义

        4.3.2 变量调用

        4.3.3 变量查看

        4.3.4 变量删除

    4.4 环境变量

        4.4.1 环境变量设置

        4.4.2 环境变量查询

        4.4.3 环境变量删除

        4.4.4 系统默认环境变量

        4.4.5 PATH 变量

        4.4.6 PS1 变量 

        4.4.7 LANG 语系变量

    4.5 位置参数变量

    4.6 预定义变量

    4.7 接收键盘输入

四、Bash 变量

4.1 变量的定义

在定义变量时,有一些规则需要遵守:

  • 变量名称可以由字母、数字和下划线组成,但是不能以数字开头。如果变量名是“2name”则是错误的。

  • 在 Bash 中,变量的默认类型都是字符串型,如果要进行数值运算,则必修指定变量类型为数值型。

  • 变量用等号连接值,等号左右两侧不能有空格。

  • 变量的值如果有空格,需要使用单引号或双引号包括。如:“test="hello world!”
    。其中双引号括起来的内容“$”
    “\”
    和反引号都拥有特殊含义,而单引号括起来的内容都是普通字符。

  • 在变量的值中,可以使用“\”
    转义符。

  • 如果需要增加变量的值,那么可以进行变量值的叠加。不过变量需要用双引号包含"$变量名"
    或用${变量名}
    包含变量名。例如:

 [root@localhost ~]# test=123
 [root@localhost ~]# test="$test"456
 [root@localhost ~]# echo $test
 123456
 #叠加变量 test,变量值变成了 123456
 [root@localhost ~]# test=${test}789
 [root@localhost ~]# echo $test
 123456789
 #再叠加变量 test,变量值编程了 123456789

变量值的叠加可以使用两种格式:“$变量名”
${变量名}

  • 如果是把命令的结果作为变量值赋予变量,则需要使用反引号或$()包含命令。例如:

 [root@localhost ~]# test=$(date)
 [root@localhost ~]# echo $test
 2021 06 12 星期六 11:27:50 CST

  • 环境变量名建议大写,便于区分。

4.2 变量的分类

  • 用户自定义变量:这种变量是最常见的变量,由用户自由定义变量名和变量的值。

  • 环境变量:这种变量中主要保存的是和系统操作环境相关的数据,比如当前登录用户,用户的家目录,命令的提示符等。不是太好理解吧,那么大家还记得在 Windows 中,同一台电脑可以有多个用户登录,而且每个用户都可以定义自己的桌面样式和分辨率,这些其实就是Windows 的操作环境,可以当做是 Windows 的环境变量来理解。环境变量的变量名可以自由定义,但是一般对系统起作用的环境变量的变量名是系统预先设定好的。

  • 位置参数变量:这种变量主要是用来向脚本当中传递参数或数据的,变量名不能自定义,变量作用是固定的。

  • 预定义变量:是 Bash 中已经定义好的变量,变量名不能自定义,变量作用也是固定的。

4.3 用户自定义变量

4.3.1 变量定义

 [root@localhost ~]# 2name="test"
 -bash: 2name=test: command not found
 #变量名不能用数字开头
 [root@localhost ~]# name = "test"
 -bash: name: command not found
 #等号左右两侧不能有空格
 [root@localhost ~]# name=test bash
 -bash: test bash: command not found
 #变量的值如果有空格,必须用引号包含

4.3.2 变量调用

 [root@localhost ~]# name="hello bash"
 #定义变量 name
 [root@localhost ~]# echo $name
 hello bash
 #输出变量 name 的值

4.3.3 变量查看

 [root@localhost ~]# set [选项]
 选项:
 -u: 如果设定此选项,调用未声明变量时会报错(默认无任何提示)
 -x: 如果设定此选项,在命令执行之前,会把命令先输出一次
 +<参数>: 取消某个set曾启动的参数。

直接使用 set 命令,会查询系统中所有的变量,包含用户自定义变量和环境变量

当设置了-u 选项后,如果调用没有设定的变量会有报错。默认是没有任何输出的。

如果设定了-x 选项,会在每个命令执行之前,先把命令输出一次

4.3.4 变量删除

 [root@localhost ~]# unset 变量名

4.4 环境变量

环境变量分为系统环境变量和用户环境变量。环境变量对所有shell环境起作用,而普通变量只对当前shell环境起作用。

4.4.1 环境变量设置

 [root@localhost ~]# export age="18"
 #使用 export 声明的变量即是环境变量

4.4.2 环境变量查询

env 命令和 set 命令的区别是,set 命令可以查看所有变量,而 env 命令只能查看环境变量。

 [root@localhost ~]# env | grep age

4.4.3 环境变量删除

 [root@localhost ~]# unset age

4.4.4 系统默认环境变量

env 命令可以查询到所有的环境变量,可是还有一些变量虽然不是环境变量,却是和 Bash 操作接口相关的变量,这些变量也对 Bash 操作终端起到了重要的作用。这些变量就只能用 set 命令来查看,下面只列出重要的内容:

 [root@localhost ~]# set
 BASH=/bin/bash
 #Bash 的位置
 BASH_VERSINFO=([0]="4" [1]="1" [2]="2" [3]="1" [4]="release"
 [5]="i386-redhat-linux-gnu")
 #Bash 版本
 BASH_VERSION='4.1.2(1)-release'
 #bash 的版本
 COLORS=/etc/DIR_COLORS
 #颜色记录文件
 HISTFILE=/root/.bash_history
 #历史命令保存文件
 HISTFILESIZE=1000
 #在文件当中记录的历史命令最大条数
 HISTSIZE=1000
 #在缓存中记录的历史命令最大条数
 LANG=zh_CN.UTF-8
 #语系环境
 MACHTYPE=i386-redhat-linux-gnu
 #软件类型是 i386 兼容类型
 MAILCHECK=60
 #每 60 秒去扫描新邮件
 PPID=2166
 #父 shell 的 PID。我们当前 Shell 是一个子 shell
 PS1='[\u@\h \W]\$ '
 #命令提示符
 PS2='> '
 #如果命令一行没有输入完成,第二行命令的提示符
 UID=0
 #当前用户的 UID

4.4.5 PATH 变量

PATH 变量:系统查找命令的路径

先查询下 PATH 环境变量的值:

PATH 变量的值是用“:”
分割的路径,这些路径就是系统查找命令的路径。也就是说当我们输入了一个程序名,如果没有写入路径,系统就会到 PATH 变量定义的路径中去寻找,是否有可以执行的程序。如果找到则执行,否则会报“命令没有发现”的错误。

把脚本拷贝到 PATH 变量定义的路径中,也可以不输入路径而直接运行。

 [root@localhost ~]# cp root/sh/hello.sh bin/
 #拷贝 hello.sh 到/bin 目录
 [root@localhost ~]# hello.sh
 hello bash!
 #hello.sh 可以直接执行了

可以修改 PATH 变量的值,而不是把程序脚本复制到/bin/目录中。通过变量的叠加实现:

 [root@localhost ~]# PATH="$PATH":/root/sh
 #在变量 PATH 的后面,加入/root/sh 目录
 [root@localhost ~]# echo $PATH
 /usr/lib/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/root/sh
 #查询 PATH 的值,变量叠加生效了

当然这样定义的 PATH 变量只是临时生效,一旦重启或注销就会消失,如果想要永久生效,需要写入环境变量配置文件,后面讲解环境变量配置文件。

4.4.6 PS1 变量

PS1 变量:命令提示符设置

PS1 是一个很有意思的变量,是用来定义命令行的提示符的,可以按照我们自己的需求来定义自己喜欢的提示符。PS1 可以支持以下这些选项:

  • \d:显示日期,格式为“星期 月 日”

  • \H:显示完整的主机名。如默认主机名“localhost.localdomain”

  • \h:显示简写主机名。如默认主机名“localhost”

  • \t:显示 24 小时制时间,格式为“HH:MM:SS”

  • \T:显示 12 小时制时间,格式为“HH:MM:SS”

  • \A:显示 24 小时制时间,格式为“HH:MM”

  • \@:显示 12 小时制时间,格式为“HH:MM am/pm”

  • \u:显示当前用户名

  • \v:显示 Bash 的版本信息

  • \w:显示当前所在目录的完整名称

  • \W:显示当前所在目录的最后一个目录

  • \#:执行的第几个命令

  • \$:提示符。如果是 root 用户会显示提示符为“#”,如果是普通用户会显示提示符为“$”

这些选项该怎么用啊?我们先看看 PS1 变量的默认值吧:

默认的提示符是显示“[用户名@简写主机名 最后所在目录]提示符”

在 PS1 变量中,如果是可以解释的符号,如“\u”
“\h”
等,则显示这个符号的作用。如果是不能解释的符号,如“@”或“空格”,则原符号输出。那么我们修改下 PS1 变量,看看会出现什么情况吧:

 [root@localhost ~]# PS1='[\u@\t \w]\$ '
 #修改提示符为‘[用户名@当前时间 当前所在完整目录]提示符’
 [root@04:46:40 ~]#cd usr/local/src/
 #切换下当前所在目录,因为家目录是看不出来区别的
 [root@04:47:29 /usr/local/src]#
 #看到了吗?提示符按照我们的设计发生了变化

这里要小心,PS1 变量的值要用单引号包含,否则设置不生效。再举个例子吧:

 [root@04:50:08 /usr/local/src]#PS1='[\u@\@ \h \# \W]\$'
 [root@04:53 上午 localhost 31 src]#
 #提示符又变了。\@:时间格式是 HH:MM am/pm;\#:会显示执行了多少个命令

4.4.7 LANG 语系变量

LANG 变量定义了 Linux 系统的主语系环境,这个变量的默认值是:

这是因为我们 Linux 安装时,选择的是中文安装,所以默认的主语系变量是“zh_CN.UTF-8”。那么 Linux 中到底支持多少语系呢?可以使用以下命令查询:

支持这么多的语系,当前系统到底是什么语系呢?使用 locale 命令
直接查询:

我们还要通过文件/etc/sysconfig/i18n 定义系统的默认语系,查看下这个文件的内容:

这又是当前系统语系,又是默认语系,有没有快晕倒的感觉。解释下吧,可以这样理解,默认语系是下次重启之后系统所使用的语系,而当前系统语系是当前系统使用的语系。如果系统重启,会从默认语系配置文件/etc/sysconfig/i18n
中读出语系,然后赋予变量 LANG 让这个语系生效。也就是说,LANG 定义的语系只对当前系统生效,要想永久生效就要修改/etc/sysconfig/i18n 文件了。

4.5 位置参数变量

位置参数变量作用
$nn 为数字,$0 代表命令本身,$1-$9 代表第一到第九个参数,十以上的参数需要用大括号包含,如${10}.
$*这个变量代表命令行中所有的参数,$*把所有的参数看成一个整体
$@这个变量也代表命令行中所有的参数,不过$@把每个参数区分对待
$#这个变量代表命令行中所有参数的个数

 [root@localhost sh]# vi count.sh
 #!/bin/bash
 
 num1=$1
 #给 num1 变量赋值是第一个参数
 num2=$2
 #给 num2 变量赋值是第二个参数
 sum=$(( $num1 + $num2))
 #变量 sum 的和是 num1 加 num2
 echo $sum
 #打印变量 sum 的值

那么还有几个位置参数变量是干嘛的呢?我们在写个脚本来说明下

 [root@localhost sh]# vi parameter.sh
 #!/bin/bash
 
 echo "A total of $# parameters"
 #使用$#代表所有参数的个数
 echo "The parameters is: $*"
 #使用$*代表所有的参数
 echo "The parameters is: $@"
 #使用$@也代表所有参数

那么“$*”和“$@”有区别吗?还是有区别的,$*会把接收的所有参数当成一个整体对待,而$@则会区分对待接收到的所有参数。还是举个例子:

 [root@localhost sh]# vi parameter2.sh
 #!/bin/bash
 
 for i in "$*"
 #定义 for 循环,in 后面有几个值,for 会循环多少次,注意“$*”要用双引号括起来
 #每次循环会把 in 后面的值赋予变量 i
 #Shell 把$*中的所有参数看成是一个整体,所以这个 for 循环只会循环一次
  do
  echo "The parameters is: $i"
 #打印变量$i 的值
  done
 x=1
 #定义变量 x 的值为 1
 for y in "$@"
 #同样 in 后面的有几个值,for 循环几次,每次都把值赋予变量 y #可是 Shell 中把“$@”中的每个参数都看成是独立的,所以“$@”中有几个参数,就会循环几次
  do
  echo "The parameter$x is: $y"
 #输出变量 y 的值
  x=$(( $x +1 ))
 #然变量 x 每次循环都加 1,为了输出时看的更清楚
  done

4.6 预定义变量

预定义变量作用
$?最后一次执行的命令的返回状态。如果这个变量的值为 0,证明上一个命令正确执行;如果这个变量的值为非 0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了
$$当前进程的进程号(PID)
$!后台运行的最后一个进程的进程号(PID)

我们先来看看“$?”这个变量,看起来不好理解,我们还是举个例子:

 [root@localhost sh]# ls
 count.sh hello.sh parameter2.sh parameter.sh
 #ls 命令正确执行
 [root@localhost sh]# echo $?
 0
 #预定义变量“$?”的值是 0,证明上一个命令执行正确
 [root@localhost sh]# ls install.log
 ls: 无法访问 install.log: 没有那个文件或目录
 #当前目录中没有 install.log 文件,所以 ls 命令报错了
 [root@localhost sh]# echo $?
 2
 #变量“$?”返回一个非 0 的值,证明上一个命令没有正确执行
 #至于错误的返回值到底是多少,是在编写 ls 命令时定义好的,如果碰到文件不存在就返回数值 2

接下来我们来说明下“$$”和“$!”这两个预定义变量,我们写个脚本吧:

 [root@localhost sh]# vi variable.sh
 #!/bin/bash
 
 echo "The current process is $$"
 #输出当前进程的 PID。;
 #这个 PID 就是 variable.sh 这个脚本执行时,生成的进程的 PID
 find /root -name hello.sh &
 #使用 find 命令在 root 目录下查找 hello.sh 文件
 #符号&的意思是把命令放入后台执行,工作管理在系统管理章节详细介绍
 echo "The last one Daemon process is $!"
 #输出这个后台执行命令的进程的 PID,也就是输出 find 命令的 PID 号

4.7 接收键盘输入

 [root@localhost ~]# read [选项] [变量名]
 选项:
 -p “提示信息”: 在等待 read 输入时,输出提示信息
 -t 秒数: read 命令会一直等待用户输入,使用此选项可以指定等待时间
 -n 字符数: read 命令只接受指定的字符数,就会执行
 -s: 隐藏输入的数据,适用于机密信息的输入
 变量名:
 变量名可以自定义,如果不指定变量名,会把输入保存入默认变量 REPLY
 如果只提供了一个变量名,则整个输入行赋予该变量
 如果提供了一个以上的变量名,则输入行分为若干字,一个接一个地赋予各个变量,而命令行上的最后一个变量取得剩余的所有字

写个例子来解释下 read 命令:

 [root@localhost sh]# vi read.sh
 #!/bin/bash
 
 read -t 30 -p "Please input your name: " name
 #提示“请输入姓名”并等待 30 秒,把用户的输入保存入变量 name 中
 echo "Name is $name"
 #看看变量“$name”中是否保存了你的输入
 read -s -t 30 -p "Please enter your age: " age
 #提示“请输入年龄”并等待 30 秒,把用户的输入保存入变量 age 中 #年龄是隐私,所以我们用“-s”选项隐藏输入
 echo -e "\n"
 #调整输出格式,如果不输出换行,一会的年龄输出不会换行
 echo "Age is $age"
 read -n 1 -t 30 -p "Please select your gender[M/F]: " gender
 #提示“请选择性别”并等待 30 秒,把用户的输入保存入变量 gender
 #使用“-n 1”选项只接收一个输入字符就会执行(都不用输入回车)
 echo -e "\n"
 echo "Sex is $gender"






推荐阅读
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • Skywalking系列博客1安装单机版 Skywalking的快速安装方法
    本文介绍了如何快速安装单机版的Skywalking,包括下载、环境需求和端口检查等步骤。同时提供了百度盘下载地址和查询端口是否被占用的命令。 ... [详细]
  • 在CentOS/RHEL 7/6,Fedora 27/26/25上安装JAVA 9的步骤和方法
    本文介绍了在CentOS/RHEL 7/6,Fedora 27/26/25上安装JAVA 9的详细步骤和方法。首先需要下载最新的Java SE Development Kit 9发行版,然后按照给出的Shell命令行方式进行安装。详细的步骤和方法请参考正文内容。 ... [详细]
  • Linux如何安装Mongodb的详细步骤和注意事项
    本文介绍了Linux如何安装Mongodb的详细步骤和注意事项,同时介绍了Mongodb的特点和优势。Mongodb是一个开源的数据库,适用于各种规模的企业和各类应用程序。它具有灵活的数据模式和高性能的数据读写操作,能够提高企业的敏捷性和可扩展性。文章还提供了Mongodb的下载安装包地址。 ... [详细]
  • 如何用JNI技术调用Java接口以及提高Java性能的详解
    本文介绍了如何使用JNI技术调用Java接口,并详细解析了如何通过JNI技术提高Java的性能。同时还讨论了JNI调用Java的private方法、Java开发中使用JNI技术的情况以及使用Java的JNI技术调用C++时的运行效率问题。文章还介绍了JNIEnv类型的使用方法,包括创建Java对象、调用Java对象的方法、获取Java对象的属性等操作。 ... [详细]
  • STM32与FPGA的对比及学习建议
    本文对比了野火STM32F103指南针板和Xilinx的PYNQ-Z2板(ZYNQ-7020),介绍了野火STM32F103指南针板的学习资料和讲解视频的详细程度,建议初学者学习野火的资料。同时,介绍了STM32开发所用的Keil程序和C指针的重要性。对于ZYNQ-7020的开发,提到了其自带的Linux、Ubuntu18.4系统以及使用SD卡烧入镜像的方法。 ... [详细]
  • 本文介绍了2015年九月八日的js学习总结及相关知识点,包括参考书《javaScript Dom编程的艺术》、js简史、Dom、DHTML、解释型程序设计和编译型程序设计等内容。同时还提到了最佳实践是将标签放到HTML文档的最后,并且对语句和注释的使用进行了说明。 ... [详细]
  • 如何修改MySQL数据库密码的方法及步骤详解
    本文详细介绍了四种修改MySQL数据库密码的方法,包括使用SET PASSWORD命令、mysqladmin命令、UPDATE语句直接编辑user表的步骤和操作示例。通过本文的指导,读者可以轻松掌握修改MySQL数据库密码的技巧和方法。 ... [详细]
  • Python已成为全球最受欢迎的编程语言之一,然而Python程序的安全运行存在一定的风险。本文介绍了Python程序安全运行需要满足的三个条件,即系统路径上的每个条目都处于安全的位置、"主脚本"所在的目录始终位于系统路径中、若python命令使用-c和-m选项,调用程序的目录也必须是安全的。同时,文章还提出了一些预防措施,如避免将下载文件夹作为当前工作目录、使用pip所在路径而不是直接使用python命令等。对于初学Python的读者来说,这些内容将有所帮助。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • PHP设置MySQL字符集的方法及使用mysqli_set_charset函数
    本文介绍了PHP设置MySQL字符集的方法,详细介绍了使用mysqli_set_charset函数来规定与数据库服务器进行数据传送时要使用的字符集。通过示例代码演示了如何设置默认客户端字符集。 ... [详细]
  • 本文是一位90后程序员分享的职业发展经验,从年薪3w到30w的薪资增长过程。文章回顾了自己的青春时光,包括与朋友一起玩DOTA的回忆,并附上了一段纪念DOTA青春的视频链接。作者还提到了一些与程序员相关的名词和团队,如Pis、蛛丝马迹、B神、LGD、EHOME等。通过分享自己的经验,作者希望能够给其他程序员提供一些职业发展的思路和启示。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 本文介绍了绕过WAF的XSS检测机制的方法,包括确定payload结构、测试和混淆。同时提出了一种构建XSS payload的方法,该payload与安全机制使用的正则表达式不匹配。通过清理用户输入、转义输出、使用文档对象模型(DOM)接收器和源、实施适当的跨域资源共享(CORS)策略和其他安全策略,可以有效阻止XSS漏洞。但是,WAF或自定义过滤器仍然被广泛使用来增加安全性。本文的方法可以绕过这种安全机制,构建与正则表达式不匹配的XSS payload。 ... [详细]
  • 在加载一个第三方厂商的dll文件时,提示“找不到指定模块,加载失败”。由于缺乏必要的技术支持,百思不得期间。后来发现一个有用的工具 ... [详细]
author-avatar
中华oc博弈网络志
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有